package com.link.base.base.product.service;

import com.link.base.base.product.dao.mybatis.mapper.ProdQuoteMapper;
import com.link.base.base.product.model.PartsCost;
import com.link.base.base.product.model.ProdQuote;
import com.link.base.base.project.model.QuoteRound;
import com.link.base.base.project.service.QuoteRoundService;
import com.link.base.core.basic.util.BigDecimalUtils;
import com.link.core.basic.dao.mapper.BasicMapper;
import com.link.core.basic.service.BasicServiceException;
import com.link.core.basic.service.BasicServiceImpl;
import com.link.core.basic.service.ServiceException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 零件报价表
 *
 * @author 阳晓琳
 * @date 2020-10-16 17:19:06
 */
@Service
public class ProdQuoteServiceImpl extends BasicServiceImpl<ProdQuote> implements ProdQuoteService {

    private static final Logger logger = LogManager.getLogger(ProdQuoteServiceImpl.class);

    public static BigDecimal ZERO = new BigDecimal(0);

    @Resource
    private ProdQuoteMapper    prodQuoteMapper;

    @Resource
    private PartsBasicInfoService partsBasicInfoService;

    @Resource
    private PartsCostService partsCostService;

    @Resource
    private QuoteRoundService quoteRoundService;

    @Override
    public BasicMapper<ProdQuote> getBasicMapper() {
        return prodQuoteMapper;
    }

    @Override
    public List<ProdQuote> queryByProType(ProdQuote prodQuote) throws Exception {
        return prodQuoteMapper.queryAll(prodQuote);
    }

    /**
     * 根据预设利率计算总成报价
     * 将预设利率存入总成与零件的利率值字段
     * @param entity
     */
    @Override
    public void presetRateCalcul(ProdQuote entity) throws Exception {
        //1.点击确定，将预设利率的值赋给当前总成行ID的对应子零件利率值字段，若预设利率等于Custom时，无需赋值
        //1.1取前端传过来的当前行总成报价id，去零件报价表根据id查询总成信息，总成插入对应利率值
        ProdQuote prodQuote = new ProdQuote();
        prodQuote.setId(Long.valueOf(entity.getAttr1()));
        ProdQuote record = prodQuoteMapper.queryById(prodQuote);
        if (record == null) {
            throw new ServiceException("IYUQUOTE-300");
        }
        //判断预设利率途径
        if (ZERO.compareTo(entity.getDefaultRate()) != 0) {
            record.setDefaultRate(entity.getDefaultRate());
            record.setDefineRate(entity.getDefaultRate());
        } else {
            record.setDefaultRate(entity.getDefaultRate());
            record.setDefineRate(entity.getDefineRate());
        }

        //2.根据利率得到初始参考值
        //基础变量
        BigDecimal one = new BigDecimal(1);
        BigDecimal factorySysNum = new BigDecimal(0.13);
        BigDecimal s9 = new BigDecimal(3600);
        BigDecimal s11 = new BigDecimal(13200);
        BigDecimal s12 = new BigDecimal(5);
        //1-利率
        BigDecimal f1 = one.subtract(record.getDefineRate());
        //1-容器损耗
        BigDecimal vesselLoss = changeNullToZero(record.getVesselLoss());
        BigDecimal f2 = one.subtract(vesselLoss);
        //商务价格（未含模摊） = （工厂成本（未含模摊）/（1-预设利率）
        BigDecimal factoryCost = changeNullToZero(record.getFactoryCost());
        BigDecimal businessPrice = ZERO;
        if (!checkZero(f1)) {
            businessPrice = factoryCost.divide(f1,7, BigDecimal.ROUND_HALF_UP);
        }

        //管利费  = 工厂成本（未含模摊）*13%
        BigDecimal manaProFee = changeNullToZero(factoryCost.multiply(factorySysNum));
        record.setManaProFee(manaProFee);
        //大系数分子
        BigDecimal freight = changeNullToZero(record.getFreight());
        BigDecimal s3 = businessPrice.subtract(manaProFee.add(freight));
        //大系数分母
        BigDecimal materialPrice = changeNullToZero(record.getMaterialPrice());
        BigDecimal outBuyTotalPrice = changeNullToZero(record.getOutBuyTotalPrice());
        BigDecimal manufactCost = changeNullToZero(record.getManufactCost());
        BigDecimal shipPackagePri = changeNullToZero(record.getShipPackagePri());
        BigDecimal experimentCost = changeNullToZero(record.getExperimentCost());
        BigDecimal s4 = materialPrice.add(outBuyTotalPrice).add(manufactCost).add(shipPackagePri).add(experimentCost);
        //大系数  = （商务价格（未含模摊）-运输费-管利费）/（总成材料价格+总成外购/外协总价+总成直接制造成本+出货包装单价+实验费）
        BigDecimal s5 = s3.divide(s4,7, BigDecimal.ROUND_HALF_UP);

        //1.2根据上面查到的总成报价信息，利用总成零件ID去项目成本信息表中查询该总成的零部件成本信息
        PartsCost partsCostEntity = new PartsCost();

        /*
         throw new RuntimeException("对象变更，请联系管理员!");
        partsCostEntity.setcRMAssemblysId(record.getcRMPartId());
        partsCostEntity.setProjectId(record.getProjectHeadId());
        List<PartsCost> partsCostList = partsCostService.queryByParts(partsCostEntity);
         */
        List<PartsCost> partsCostList = new ArrayList<>();


        //1.3遍历查询到的零件ID，去零件报价表关联零件成本表查询对应零件，对每个零件的利率值字段赋值  不需要
        //总成汇总字段
        BigDecimal totalWeight = ZERO;
        BigDecimal totalMaPrice = ZERO;
        BigDecimal totalOutPrice = ZERO;
        BigDecimal totalMakeCost = ZERO;
        BigDecimal totalMoldFee = ZERO;
        BigDecimal totalInspectionFee = ZERO;
        BigDecimal totalSpecEquipCost = ZERO;
        BigDecimal totalAvgCarCostPrice = ZERO;

        for (PartsCost partsCost : partsCostList) {
            // prodQuote.setcRMPartId(partsCost.getcRMPartId()); 对象变更
            prodQuote.setProjectHeadId(record.getProjectHeadId());
            prodQuote.setQuoteRoundId(record.getQuoteRoundId());
            //找到该总成的所属零件报价
            ProdQuote prodQuotePart = prodQuoteMapper.queryByCRMPartId(prodQuote);
            if (prodQuotePart != null) {
                if (ZERO.compareTo(entity.getDefaultRate()) != 0) {
                    prodQuotePart.setDefaultRate(entity.getDefaultRate());
                    prodQuotePart.setDefineRate(entity.getDefaultRate());
                } else {
                    prodQuotePart.setDefaultRate(entity.getDefaultRate());
                    prodQuotePart.setDefineRate(entity.getDefineRate());
                }
                //零件材料单价 = 大系数 * 零件材料单价
                BigDecimal materialUnitPri = changeNullToZero(prodQuotePart.getMaterialUnitPri());
                prodQuotePart.setMaUnitPrice(s5.multiply(materialUnitPri));
                //材料价格 = 数量*材料单价*产品毛重/1000。材料单价为新计算的值，其余值来源：零件成本表    材料价格放到sql写
                BigDecimal unit = new BigDecimal(1000);
                BigDecimal timeUnit = new BigDecimal(3600);
                BigDecimal num = changeNullToZero(prodQuotePart.getPerCar());
                BigDecimal maUnitPrice = changeNullToZero(prodQuotePart.getMaUnitPrice());
                BigDecimal prodRoughWeight = changeNullToZero(prodQuotePart.getRoughWeight());
                BigDecimal maPrice = num.multiply(maUnitPrice).multiply(prodRoughWeight).divide(unit,7, BigDecimal.ROUND_HALF_UP);
                prodQuotePart.setMaPrice(maPrice);
                //外购单价 = 大系数 *外购单价
                BigDecimal outBuyUnitPrice = changeNullToZero(prodQuotePart.getOutBuyUnitPrice());
                prodQuotePart.setOutUnitPrice(s5.multiply(outBuyUnitPrice));
                //计算外购总价 外购总价(元)=数量*外购单价
                BigDecimal outUnitPrice = changeNullToZero(prodQuotePart.getOutUnitPrice());
                BigDecimal outTotalPrice = num.multiply(outUnitPrice);
                prodQuotePart.setOutTotalPrice(outTotalPrice);

                //生产节拍时间 = 大系数 *生产节拍时间
                BigDecimal prodBeatTime = changeNullToZero(prodQuotePart.getProdBeatTime());
                prodQuotePart.setBeatTime(s5.multiply(prodBeatTime));
                //作业人数
                BigDecimal workNum = changeNullToZero(prodQuotePart.getWorkNum());
                //人工单小时成本
                BigDecimal peoHourCost = changeNullToZero(prodQuotePart.getPeoHourCost());
                //生产节拍时间
                BigDecimal beatTime = changeNullToZero(prodQuotePart.getBeatTime());
                //型腔数
                BigDecimal cavityNum = changeNullToZero(prodQuotePart.getCavityNum());
                //设备稼动率
                BigDecimal equipActivation = changeNullToZero(prodQuotePart.getEquipActivation());
                BigDecimal equipHourCost = changeNullToZero(prodQuotePart.getEquipHourCost());
                //除数为0 则计算结果为0
                BigDecimal equipFee = ZERO;
                BigDecimal peoCost = ZERO;
                if (checkZero(cavityNum)) {
                    prodQuotePart.setEquipFee(ZERO);
                    prodQuotePart.setPeoFee(ZERO);
                } else if (checkZero(equipActivation)) {
                    prodQuotePart.setPeoFee(ZERO);
                    //设备费用(元)=设备单小时成本*生产节拍时间/3600/型腔数;除数为0，数据和上面合一
                    equipFee = equipHourCost.multiply(beatTime).divide((timeUnit.multiply(cavityNum)),7,BigDecimal.ROUND_HALF_UP);
                } else {
                    //人工费用(元)=作业人数*人工单小时成本/（3600/生产节拍时间*型腔数）/设备稼动率
                    //人工费用(元)=作业人数*人工单小时成本*生产节拍时间/（3600*型腔数*设备稼动率） 公式变种
                    peoCost = workNum.multiply(peoHourCost).multiply(beatTime)
                            .divide((timeUnit.multiply(cavityNum).multiply(equipActivation)),7,BigDecimal.ROUND_HALF_UP);
                    prodQuotePart.setPeoFee(peoCost);
                    //设备费用(元)=设备单小时成本*生产节拍时间/3600/型腔数;除数为0，数据和上面合一
                    equipFee = equipHourCost.multiply(beatTime).divide((timeUnit.multiply(cavityNum)),7,BigDecimal.ROUND_HALF_UP);
                }
                prodQuotePart.setEquipFee(equipFee);

                //直接制造成本(元)=人工费用+设备费用
                BigDecimal makeCost = peoCost.add(equipFee);
                prodQuotePart.setMakeCost(makeCost);

                //模具费 = 大系数 *模具费
                BigDecimal mouldCost = changeNullToZero(prodQuotePart.getMouldCost());
                prodQuotePart.setToolFee(s5.multiply(mouldCost));
                //检具费 = 大系数 *检具费
                BigDecimal inspectionCost = changeNullToZero(prodQuotePart.getInspectionCost());
                prodQuotePart.setSubmitFee(s5.multiply(inspectionCost));
                //专用设备费用 = 大系数 *专用设备费用
                BigDecimal specialEquipCost = changeNullToZero(prodQuotePart.getSpecialEquipCost());
                prodQuotePart.setSpecEquipFee(s5.multiply(specialEquipCost));

                //汇总商务价格
                totalMaPrice = totalMaPrice.add(maPrice);
                totalWeight = totalWeight.add(prodQuotePart.getNetWeight());
                totalOutPrice = totalOutPrice.add(outTotalPrice);
                totalMakeCost = totalMakeCost.add(makeCost);
                totalMoldFee = totalMoldFee.add(prodQuotePart.getToolFee());
                totalInspectionFee = totalInspectionFee.add(prodQuotePart.getSubmitFee());
                totalSpecEquipCost = totalSpecEquipCost.add(prodQuotePart.getSpecEquipFee());

                prodQuotePart.setAttr1("partInfo");
                prodQuoteMapper.update(prodQuotePart);
            } else {
                // 插入报价数据
            }
        }
        //插入总成数据
        record.setMaPrice(totalMaPrice);
        record.setNetWeight(totalWeight);
        record.setOutTotalPrice(totalOutPrice);
        record.setMakeCost(totalMakeCost);
        record.setToolFee(totalMoldFee);
        record.setSubmitFee(totalInspectionFee);
        record.setSpecEquipFee(totalSpecEquipCost);
        //周转容器单价= 大系数 *周转容器单价
        BigDecimal turnoverContain = changeNullToZero(record.getTurnoverContain());
        record.setContainerUnitPrice(s5.multiply(turnoverContain));
        /*//投入容器量
        BigDecimal totalProdOutput = changeNullToZero(record.getTotalProdOutput());
        record.setInputValue(totalProdOutput.multiply(s12).divide(s11,7, BigDecimal.ROUND_HALF_UP));*/
        //投入总金额
        BigDecimal inputValue = changeNullToZero(record.getInputValue());
        BigDecimal containerUnitPrice = changeNullToZero(record.getContainerUnitPrice());
        BigDecimal inputTotalNum = inputValue.multiply(containerUnitPrice);
        record.setInputTotalAmount(inputTotalNum);
        //出货包装单件价格
        BigDecimal containerLoss = changeNullToZero(record.getContainerLoss());
        BigDecimal prodTotalNum = changeNullToZero(record.getProdTotalNum());
        BigDecimal shipPackUnitPrice = ZERO;
        //判断除数为0则 结果为0
        if (!checkZero(prodTotalNum) && !checkZero(one.subtract(containerLoss))) {
            shipPackUnitPrice = inputTotalNum.divide((prodTotalNum.multiply(one.subtract(containerLoss))),7,BigDecimal.ROUND_HALF_UP);
        }
        record.setShipPackUnitPrice(shipPackUnitPrice);
        //实验费= 大系数 *实验费
        record.setLaboratoryFee(s5.multiply(experimentCost));

        //工厂制造费用分摊 商务价格（未含模摊） 商务价格（含模摊） 毛利率 均车价
        //BigDecimal totalFactoryCost = ZERO;
        BigDecimal totalBusNoPrice = ZERO;
        BigDecimal totalBusCoPrice = ZERO;
        BigDecimal grossing = ZERO;
        BigDecimal averageCarPrice = ZERO;
        //工厂制造费用分摊 =（总成材料价格+总成外购/外协总价+总成直接制造成本+包装单件价格+实验费用）*0.02
        BigDecimal factoryCostSysNum = new BigDecimal(0.02);
        BigDecimal laboratory = changeNullToZero(record.getLaboratoryFee());
        BigDecimal totalFactoryCost = factoryCostSysNum.multiply((totalMaPrice.add(totalOutPrice)
                .add(totalMakeCost).add(shipPackUnitPrice).add(laboratory)));
        record.setFacShareCost(totalFactoryCost);

        //商务价格（未含模摊） =总成材料价格+总成外购/外协总价+总成直接制造成本+出货包装单件价格+实验费用+运输费+管利费
        BigDecimal trafficFee = changeNullToZero(record.getTrafficFee());
        totalBusNoPrice = totalMaPrice.add(totalOutPrice).add(totalMakeCost).add(shipPackUnitPrice).add(laboratory).add(trafficFee).add(manaProFee);
        record.setBusinessPriceNo(totalBusNoPrice);

        //商务价格（含模摊）：商务价格（未含模摊）+模摊费用
        BigDecimal moldCost = changeNullToZero(record.getMoldCost());
        totalBusCoPrice = totalBusNoPrice.add(moldCost);
        record.setBusinessPriceYes(totalBusCoPrice);

        //毛利率=（商务价格（未含模摊）-工厂成本（未含模摊））/商务价格（未含模摊）
        if (!checkZero(totalBusNoPrice)) {
            grossing = (totalBusNoPrice.subtract(factoryCost)).divide(totalBusNoPrice,7,BigDecimal.ROUND_HALF_UP);
        }
        record.setGrossMargin(grossing);

        //均车价= 商务价格（未含模摊）*装车比*数量
        BigDecimal loadingRatio = changeNullToZero(record.getLoadingRatio());
        BigDecimal perCar = changeNullToZero(record.getPerCar());
        averageCarPrice = totalBusNoPrice.multiply(loadingRatio).multiply(perCar);
        record.setAverageCarPrice(averageCarPrice);

        totalAvgCarCostPrice = factoryCost.multiply(loadingRatio).multiply(perCar);
        record.setPartAvgCarCost(totalAvgCarCostPrice);

        prodQuoteMapper.update(record);
    }



    @Override
    public void deleteByQuoteId(ProdQuote prodQuote) {
        prodQuoteMapper.deleteByQuoteId(prodQuote);
    }

    /**
     * 根据项目ID 最新报价轮次 查询总成报价 返回给picklist
     * @param prodQuote
     * @return
     * @throws Exception
     */
    @Override
    public List<ProdQuote> queryAllByQuote(ProdQuote prodQuote) throws Exception {
        QuoteRound queryRound = new QuoteRound();
        queryRound.setProjectHeadId(prodQuote.getProjectHeadId());
        //根据项目ID查询最新报价伦次de 轮次
        List<QuoteRound> quoteRounds = quoteRoundService.queryByProjectId(queryRound);
        Long round = new Long(0);
        if (!quoteRounds.isEmpty() && queryRound != null) {
            QuoteRound quoteRound = quoteRounds.get(0);
            round = quoteRound.getQuoteRound();
        }
        prodQuote.setQuoteRound(round);
        //根据项目ID 最新报价轮次 查询总成报价 返回给picklist
        List<ProdQuote> prodQuotes = prodQuoteMapper.queryAll(prodQuote);
        return prodQuotes;
    }

    @Override
    public void beforInsert(ProdQuote prodQuote) throws Exception {
        if ("assemblyParts".equals(prodQuote.getAttr2())) {

            throw new RuntimeException("对象变更，请联系管理员!");
            /**
            //走总成新增逻辑
            //1.1 查询总成件成本信息 (不用考虑当前报价类型，因为切换报价类型不会继承上一报价类型的最新报价信息)
            PartsCost partsCostEntity = new PartsCost();
            Long crmPartId = prodQuote.getcRMPartId();
            partsCostEntity.setProjectId(prodQuote.getProjectHeadId());
            partsCostEntity.setcRMPartId(crmPartId);
            //logger.info(crmPartId);
            List<PartsCost> partsCosts = partsCostService.queryByAssemblyParts(partsCostEntity);
            if (partsCosts.size() > 1) {
                throw new ServiceException("PRODQUOTE-001");
            } else if (partsCosts.size() == 0) {
                throw new ServiceException("PRODQUOTE-002");
            }
            PartsCost prodCost = partsCosts.get(0);
            //**必须拿到零件成本ID。才能join到想要的成本价格。没有成本ID，查不到信息**
            prodQuote.setPartCostId(prodCost.getId());
            prodQuote.setWorkProcedure(prodCost.getWorkProcedure());
            prodQuote.setTrafficFee(prodCost.getFreight());
            prodQuote.setApportionment(prodCost.getApportionment());
            //模摊费用
            prodQuote.setMoldCost(prodCost.getMoldCost());
            prodQuote.setFactoryCostMold(prodCost.getFactoryCostMold());
            prodQuote.setNetWeight(prodCost.getProdNetWet());
            prodQuote.setWrapperType(prodCost.getContainerType());
            prodQuote.setContainerSize(prodCost.getContainerSize());
            prodQuote.setInputValue(prodCost.getInputContainer());
            prodQuote.setInputTotalAmount(prodCost.getTotalLnvest());
            prodQuote.setProdTotalNum(prodCost.getTotalProdOutput());
            prodQuote.setContainerLoss(prodCost.getVesselLoss());
            //周转容器单价
            prodQuote.setContainerUnitPrice(prodCost.getTurnoverContain());
            //专用设备费
            prodQuote.setSpecEquipFee(prodCost.getSpecialEquipCost());
            //实验费用
            prodQuote.setLaboratoryFee(prodCost.getExperimentCost());

            //总成材料价格
            prodQuote.setMaPrice(prodCost.getMaterialPrice());
            //总成外购费用
            prodQuote.setOutTotalPrice(prodCost.getOutBuyTotalPrice());
            //总成直接制造成本
            prodQuote.setMakeCost(prodCost.getManufactCost());
            //总成模具费
            prodQuote.setToolFee(prodCost.getMoldCost());
            //总成检具费
            prodQuote.setSubmitFee(prodCost.getInspectionCost());
            //出厂包装单件价格
            prodQuote.setShipPackUnitPrice(prodCost.getShipPackagePri());
            //工厂制造费用分摊
            prodQuote.setFacShareCost(prodCost.getFactoryCostAll());

            BigDecimal factorySysNum = new BigDecimal(0.13);
            BigDecimal factoryCost = changeNullToZero(prodCost.getFactoryCost());
            //管利费  = 工厂成本（未含模摊）*13%
            BigDecimal manaProFee = changeNullToZero(factoryCost.multiply(factorySysNum));
            prodQuote.setManaProFee(manaProFee);
             */
        }
    }

    public boolean checkZero(BigDecimal number) {
        if (number.compareTo(ZERO) == 0) {
            return true;
        } else {
            return false;
        }
    }

    public BigDecimal changeNullToZero(BigDecimal number) throws Exception {
        if (number == null) {
            return ZERO;
        }
        return number;
    }

    @Override
    public ProdQuote queryById(ProdQuote entity) throws Exception {
        ProdQuote record = super.queryById(entity);
        ProdQuote result = getTotalPartPrice(record);
        return result;
    }

    @Override
    public List<ProdQuote> queryByExamplePage(ProdQuote entity) throws Exception {
        List<ProdQuote> resultList = super.queryByExamplePage(entity);
        if (resultList.size() > 0) {
            for (ProdQuote prodQuote : resultList) {
                getTotalPartPrice(prodQuote);
            }
        }
        return resultList;
    }

    @Override
    public List<ProdQuote> queryAll(ProdQuote entity) throws Exception {
        List<ProdQuote> resultList = super.queryAll(entity);
        if (resultList.size() > 0) {
            for (ProdQuote prodQuote : resultList) {
                getTotalPartPrice(prodQuote);
            }
        }
        return resultList;
    }

    public ProdQuote getTotalPartPrice(ProdQuote record) throws Exception {
        BigDecimal factoryCost = changeNullToZero(record.getFactoryCost());
        BigDecimal loadingRatio = changeNullToZero(record.getLoadingRatio());
        BigDecimal perCar = changeNullToZero(record.getPerCar());
        BigDecimal totalAvgCarCostPrice = factoryCost.multiply(loadingRatio).multiply(perCar);
        record.setPartAvgCarCost(totalAvgCarCostPrice);
        BigDecimal acctPrice = BigDecimalUtils.changeNullToZero(record.getAcctPrice());
        if (!(acctPrice.compareTo(BigDecimal.ZERO) == 0)) {
            //客户价格毛利率 =（客户价格-工厂成本（未含模摊））/客户价格。工厂成本（未含模摊）值来源：零件成本表。
            BigDecimal acctPriGrossMargin = (acctPrice.subtract(factoryCost)).divide(acctPrice,4,BigDecimal.ROUND_HALF_UP);
            record.setAcctPriGrossMargin(acctPriGrossMargin);
            //客户价格均车价 = 客户价格*装车比*数量
            BigDecimal acctPartAvgPri = acctPrice.multiply(loadingRatio).multiply(perCar);
            record.setAcctPriceCarPrice(acctPartAvgPri);
        }
        /*if (record.getDefaultRate() == null) {
            return record;
        }*/
        //判断预设利率途径
        if (record.getDefaultRate() != null && ZERO.compareTo(record.getDefaultRate()) != 0) {
            record.setDefineRate(record.getDefaultRate());
        } else {
            record.setDefineRate(record.getDefineRate());
        }
        //2.根据利率得到初始参考值
        //基础变量
        BigDecimal one = new BigDecimal(1);


        //投入总金额
        BigDecimal inputValue = changeNullToZero(record.getInputValue());
        BigDecimal containerUnitPrice = changeNullToZero(record.getContainerUnitPrice());
        BigDecimal inputTotalNum = inputValue.multiply(containerUnitPrice);
        record.setInputTotalAmount(inputTotalNum);
        //出货包装单件价格
        BigDecimal containerLoss = changeNullToZero(record.getContainerLoss());
        BigDecimal prodTotalNum = changeNullToZero(record.getProdTotalNum());
        BigDecimal shipPackUnitPrice = ZERO;
        //判断除数为0则 结果为0
        if (!checkZero(prodTotalNum) && !checkZero(one.subtract(containerLoss))) {
            shipPackUnitPrice = inputTotalNum.divide((prodTotalNum.multiply(one.subtract(containerLoss))),7,BigDecimal.ROUND_HALF_UP);
        }
        record.setShipPackUnitPrice(shipPackUnitPrice);

        //工厂制造费用分摊 商务价格（未含模摊） 商务价格（含模摊） 毛利率 均车价
        BigDecimal totalBusNoPrice = ZERO;
        BigDecimal totalBusCoPrice = ZERO;
        BigDecimal grossing = ZERO;
        BigDecimal averageCarPrice = ZERO;
        //工厂制造费用分摊 =（总成材料价格+总成外购/外协总价+总成直接制造成本+包装单件价格+实验费用）*0.02
        BigDecimal factoryCostSysNum = new BigDecimal(0.02);
        //实验费= 大系数 *实验费(shoushu
        BigDecimal laboratory = changeNullToZero(record.getLaboratoryFee());

        BigDecimal totalMaPrice = changeNullToZero(record.getMaPrice());
        BigDecimal totalOutPrice = changeNullToZero(record.getOutTotalPrice());
        BigDecimal totalMakeCost = changeNullToZero(record.getMakeCost());


        BigDecimal totalFactoryCost = factoryCostSysNum.multiply((totalMaPrice.add(totalOutPrice)
                .add(totalMakeCost).add(shipPackUnitPrice).add(laboratory)));
        record.setFacShareCost(totalFactoryCost);

        //商务价格（未含模摊） =总成材料价格+总成外购/外协总价+总成直接制造成本+出货包装单件价格+实验费用+运输费+管利费
        BigDecimal trafficFee = changeNullToZero(record.getTrafficFee());
        BigDecimal manaProFee = changeNullToZero(record.getManaProFee());
        totalBusNoPrice = totalMaPrice.add(totalOutPrice).add(totalMakeCost).add(shipPackUnitPrice).add(laboratory).add(trafficFee).add(manaProFee);
        record.setBusinessPriceNo(totalBusNoPrice);

        //商务价格（含模摊）：商务价格（未含模摊）+模摊费用
        BigDecimal moldCost = changeNullToZero(record.getMoldCost());
        totalBusCoPrice = totalBusNoPrice.add(moldCost);
        record.setBusinessPriceYes(totalBusCoPrice);

        //毛利率=（商务价格（未含模摊）-工厂成本（未含模摊））/商务价格（未含模摊）
        if (!checkZero(totalBusNoPrice)) {
            grossing = (totalBusNoPrice.subtract(factoryCost)).divide(totalBusNoPrice,7,BigDecimal.ROUND_HALF_UP);
        }
        record.setGrossMargin(grossing);

        //均车价= 商务价格（未含模摊）*装车比*数量
        averageCarPrice = totalBusNoPrice.multiply(loadingRatio).multiply(perCar);
        record.setAverageCarPrice(averageCarPrice);

        return record;
    }

    @Override
    @Transactional(rollbackFor = BasicServiceException.class)
    public void beforUpdate(ProdQuote prodQuote) throws Exception {
        if ("partInfo".equals(prodQuote.getAttr1())) {
            //实时计算零件报价表中的值：材料价格、外购总价、人工费、设备费、直接制造成本
            //材料价格 = 数量*材料单价*产品毛重/1000
            BigDecimal unit = new BigDecimal(1000);
            BigDecimal timeUnit = new BigDecimal(3600);
            BigDecimal num = changeNullToZero(prodQuote.getPerCar());
            BigDecimal maUnitPrice = changeNullToZero(prodQuote.getMaUnitPrice());
            BigDecimal prodRoughWeight = changeNullToZero(prodQuote.getRoughWeight());
            BigDecimal maPrice = num.multiply(maUnitPrice).multiply(prodRoughWeight).divide(unit,7, BigDecimal.ROUND_HALF_UP);
            prodQuote.setMaPrice(maPrice);

            //计算外购总价 外购总价(元)=数量*外购单价
            BigDecimal outUnitPrice = changeNullToZero(prodQuote.getOutUnitPrice());
            BigDecimal outTotalPrice = num.multiply(outUnitPrice);
            prodQuote.setOutTotalPrice(outTotalPrice);

            //作业人数
            BigDecimal workNum = changeNullToZero(prodQuote.getWorkNum());
            //人工单小时成本
            BigDecimal peoHourCost = changeNullToZero(prodQuote.getPeoHourCost());
            //生产节拍时间
            BigDecimal beatTime = changeNullToZero(prodQuote.getBeatTime());
            //型腔数
            BigDecimal cavityNum = changeNullToZero(prodQuote.getCavityNum());
            //设备稼动率
            BigDecimal equipActivation = changeNullToZero(prodQuote.getEquipActivation());
            BigDecimal equipHourCost = changeNullToZero(prodQuote.getEquipHourCost());
            //除数为0 则计算结果为0
            BigDecimal equipFee = ZERO;
            BigDecimal peoCost = ZERO;
            if (checkZero(cavityNum)) {
                prodQuote.setEquipFee(ZERO);
                prodQuote.setPeoFee(ZERO);
            } else if (checkZero(equipActivation)) {
                prodQuote.setPeoFee(ZERO);
                //设备费用(元)=设备单小时成本*生产节拍时间/3600/型腔数;除数为0，数据和上面合一
                equipFee = equipHourCost.multiply(beatTime).divide((timeUnit.multiply(cavityNum)),7,BigDecimal.ROUND_HALF_UP);
            } else {
                //人工费用(元)=作业人数*人工单小时成本/（3600/生产节拍时间*型腔数）/设备稼动率
                //人工费用(元)=作业人数*人工单小时成本*生产节拍时间/（3600*型腔数*设备稼动率） 公式变种
                peoCost = workNum.multiply(peoHourCost).multiply(beatTime)
                        .divide((timeUnit.multiply(cavityNum).multiply(equipActivation)),7,BigDecimal.ROUND_HALF_UP);
                prodQuote.setPeoFee(peoCost);
                //设备费用(元)=设备单小时成本*生产节拍时间/3600/型腔数;除数为0，数据和上面合一
                equipFee = equipHourCost.multiply(beatTime).divide((timeUnit.multiply(cavityNum)),7,BigDecimal.ROUND_HALF_UP);
            }
            prodQuote.setEquipFee(equipFee);

            //直接制造成本(元)=人工费用+设备费用
            BigDecimal makeCost = peoCost.add(equipFee);
            prodQuote.setMakeCost(makeCost);
        }
    }

    @Override
    public void afterInsert(ProdQuote entity) throws Exception {
        if (!"noAfterInsert".equals(entity.getAttr1()) && entity.getcRMAssemblysId() == null) {

            throw new RuntimeException("对象变更，请联系管理员!");
            /**
            //查询所有零件并新增
            PartsCostBak queryCostOne = new PartsCostBak();
            queryCostOne.setProjectId(entity.getProjectHeadId());
            logger.info(entity.getcRMPartId());
            queryCostOne.setcRMAssemblysId(entity.getcRMPartId());
            List<PartsCostBak> partCostList = partsCostService.queryByParts(queryCostOne);
            for (PartsCostBak partCost : partCostList) {
                ProdQuote prodQuote = new ProdQuote();
                //标记该零件报价为本轮次
                prodQuote.setQuoteRoundId(entity.getQuoteRoundId());
                //**必须拿到零件成本ID。才能join到想要的成本价格。没有成本ID，查不到信息**
                prodQuote.setPartCostId(partCost.getId());
                prodQuote.setCraft(partCost.getTechnology());
                prodQuote.setNetWeight(partCost.getProdNetWet());
                prodQuote.setRoughWeight(partCost.getProdGrossWet());
                prodQuote.setMaPrice(partCost.getMaterialPrice());
                prodQuote.setOutUnitPrice(partCost.getOutBuyUnitPrice());
                prodQuote.setOutTotalPrice(partCost.getOutBuyTotalPrice());
                prodQuote.setProdEquip(partCost.getProdEquipment());
                prodQuote.setEquipHourCost(partCost.getEquipCostHour());
                prodQuote.setPeoHourCost(partCost.getLaborCostHour());

                prodQuote.setBeatTime(partCost.getProdBeatTime());
                prodQuote.setCavityNum(partCost.getCavityNumber());
                prodQuote.setWorkNum(partCost.getWorkerNum());

                prodQuote.setPeoFee(partCost.getLaborCost());
                prodQuote.setEquipFee(partCost.getEquipmentCost());
                prodQuote.setEquipActivation(partCost.getEquUtilizatRate());
                prodQuote.setPassPercent(partCost.getPassRate());
                prodQuote.setClassProdNum(partCost.getShiftProd());

                prodQuote.setMakeCost(partCost.getManufactCost());
                //模具费
                prodQuote.setToolFee(partCost.getMouldCost());
                prodQuote.setSubmitFee(partCost.getInspectionCost());
                prodQuote.setSpecEquipFee(partCost.getSpecialEquipCost());
                //材料单价（元）
                prodQuote.setMaUnitPrice(partCost.getMaterialUnitPri());

                prodQuote.setAttr1("noAfterInsert");

                insert(prodQuote);

            }**/
        }
    }

    @Override
    public void afterDelete(ProdQuote entity) throws Exception {
        super.afterDelete(entity);
        //根据总成id删除零件报价数据；
        deleteByAssId(entity);
    }

    private void deleteByAssId(ProdQuote entity) throws Exception {
        prodQuoteMapper.deleteByAssId(entity);
    }
}













